#include "Bindings.h"
#include "Symbol.h"

using namespace R;

Bindings* Bindings::expand(Symbol *key, Any *value, uint64_t* idx){
	R_VAR(Bindings*, old);
	R_PARAM(key);
	R_PARAM(value);
	asSelf(Bindings);

	if(self->size >= self->capacity) {
		old = self;
		self = Bindings::create(capacity<<=1);
		memcpy(self->content, old->content, old->size*sizeof(Binding));
		self->size = old->size;
	}

	self->set(self->size, key, value);

	if(idx)
		*idx = self->size;

	self->size++;

  return self;
}

// No need to check size
void Bindings::remove(uint64_t idx){
	asSelf(Bindings);

	self->content[idx] = self->content[-- self->size];
	self->content[self->size].value = self->content[self->size].key = NULL;
}

Symbol* Bindings::key(uint64_t idx){
	asSelf(Bindings);
	return self->content[idx].key;
}

Any* Bindings::get(uint64_t idx){
	asSelf(Bindings);
	return self->content[idx].value;
}

void Bindings::set(uint64_t idx, Any *value){
	R_PARAM(value);
	asSelf(Bindings);
	
	self->content[idx].value = value;
}

void Bindings::set(uint64_t idx, Symbol* key, Any *value) {
	R_PARAM(value);
	R_PARAM(key);
	asSelf(Bindings);

	self->content[idx].key = key;
	self->content[idx].value = value;
}

uint64_t Bindings::resolve(Symbol *sym){
	R_PARAM(sym);
	asSelf(Bindings);

  // This method requires that symbols are UNIQUE
	uint64_t n = self->size;
	while(n--)
		if(self->content[n].key == sym)
			return n;
	return -1;
}

Bindings* Bindings::create(uint64_t initialCapacity, uint64_t initialSize) {
	R_VAR(Bindings*, res);

	Assert(initialSize <= initialCapacity);
	
	res = static_cast<Bindings*>(operator new(sizeof(Bindings) + initialCapacity*sizeof(Binding) - sizeof(Binding), virtualVT));
	
	memset(res->content, 0, sizeof(Binding)*initialSize);

	res->capacity = initialCapacity;
	res->size     = initialSize;
	
  return res;
}
